package de.previsor.workflow.control;

import de.previsor.workflow.model.Mitarbeiter;
import de.previsor.workflow.model.TempData;
import java.io.File;
import javafx.stage.FileChooser;
import java.net.URL;
import java.util.*;
import java.util.Iterator;
import java.util.ResourceBundle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.stage.Stage;


/***
 * Klasse: AssetController
 * Dient der Steuerung von "Previsor_UI_Asset.fxml"
 * Nimmt Eingaben entgegen, verarbeitet sie und kooperiert mit der Datenbank (bzw. mit DBConnect.java)
 *
 * @author Michael Müller
 * Datum:  08.11.2014
 */
public class AssetController implements Initializable {
    
    
    private String assetPath;                // Pfad des hochzuladenden Assets auf dem lokalen Rechner
    private String assetName;                // angegebener Assetname
    private String assetErsteller;           // Author des Assets
    private String link;                     // Amazonlink --> Wichtig für 3D Möbel
    private String typ;                      // 3D / 2D / Sound ?
    private String kategorie;                // Tisch, Schrank, Bett ...
    private ArrayList<Mitarbeiter> autoren;  // Alle Mitarbeiterdaten, wird für die Angabe der Autoren benötigt

    
    
    // Felder die aus der o.g. FXML Datei angesprochen werden
    @FXML private TextField path_asset;
    @FXML private TextField inp_assetName;
    @FXML private ComboBox dd_autor;
    @FXML private TextField inp_amazonLink;
    @FXML private ComboBox dd_typ;
    @FXML private ComboBox dd_kat;
    @FXML private Button btn_fileChooser;    
    @FXML private Label lbl_fehlerHinzu;
    
    // Felder für "Optionales" ... Kategorien und Typen hinzufügen
    @FXML private TextField inp_addKat;
    @FXML private Button addKat;
    @FXML private Label lbl_addKat;
    @FXML private ComboBox dd_katOverview;
    @FXML private TextField inp_unterKat;
    @FXML private Button addUnterKat;
    @FXML private Label lbl_unterKat;
    @FXML private TextField inp_addTyp;
    @FXML private Button addTyp;
    @FXML private Label lbl_addTyp;
    
    
    /***
     * Initialisierungsmethode
     * Bestückt bzw. manipuliert die Oberfläche durch Java-Code
     * @param url wird nicht verwendet
     * @param rb wird nicht verwendet
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // Aufbau der DB Verbindung und Abfragen der Assetkategorie (wird Für Combobox benötigt)
        DBConnect con = new DBConnect();
        ArrayList<String[]> kats = con.getCategorys();
        Iterator<String[]> iter = kats.iterator();            
        
        // Für jede Kategorie wird der Combobox ein Wert hinzugefügt
        while(iter.hasNext())
            {                
               String value = iter.next()[1];
               dd_katOverview.getItems().add(value);
            }         
        
        // Dummys für den Tab "Asset hinzufügen"
        dd_autor.getItems().addAll("Will Shuter", "Henry Ford");
        dd_kat.getItems().addAll("Tisch","Schrank","Teppich","Bett");
        dd_typ.getItems().addAll("2D","3D","Sound");
        //
        dd_autor.setId("auswählen");
        lbl_fehlerHinzu.setVisible(false);
        autoren = TempData.getAllMitarbeiter();
        assetErsteller = "";
        typ            = "";
        kategorie      = "";
    }    
    
    /***
     * Nach Drücken des Speicher Buttons, werden alle Eingegebenen Daten
     * entgegengenommen und in checkData() geprüft und bei Korrektheit
     * in der Datenbank gespeichert
     * @param event 
     */
    @FXML
    private void btn_speichern(ActionEvent event)
    {
        assetPath = path_asset.getText();
        assetName = inp_assetName.getText();
        assetErsteller = String.valueOf(dd_autor.getValue());
        link = inp_amazonLink.getText();
        kategorie = String.valueOf(dd_kat.getValue());
        typ = String.valueOf(dd_typ.getValue());
        
            if(saveAssetInDB())
        {
            lbl_fehlerHinzu.setText("Speicherung erfolgreich");
            lbl_fehlerHinzu.setStyle("-fx-text-fill: green;");            
        }
    }
    /***
     * Handling für FileChooser, macht es möglich ein Asset von dem lokalen Rechner auszuwählen
     * @param event 
     */
    @FXML
    private void choose(ActionEvent event)
    {
        FileChooser fileChooser = new javafx.stage.FileChooser();
        File file = fileChooser.showOpenDialog(new Stage());

        if (file != null) path_asset.setText(file.getAbsolutePath());  
    }

    /***
     * Methode zum Prüfen der angegebenen Daten zum Tab "Asset hinzufügen"
     * @return : boolean | Sind die eingegebenen Daten korrekt?
     */
    private boolean checkData()
    {
        // Wird am Ende der Methode zurückgegeben
        boolean checkOK = true;
        // Erzeugen einer Fehlerlist
        ArrayList<String> fehler = new ArrayList<String>();
        
        // Prüfen ob Felder leer
        if(assetPath.equals("")) fehler.add("Assetpfad angeben" + TempData.lisa);        
        if(assetName.equals("")) fehler.add("Assetnamen angeben" + TempData.lisa);        
        if(assetErsteller.equals("null")) fehler.add("Autor angeben" + TempData.lisa);
        if(kategorie.equals("null")) fehler.add("Kategorie auswählen" + TempData.lisa);        
        if(typ.equals("null")) fehler.add("Typ auswählen" + TempData.lisa);
        if(!link.equals("") && !checkRegex(link)) fehler.add("Typ auswählen" + TempData.lisa);
        
        // Ausgabe der Fehlermeldungen wenn welche vorhanden
        if(!fehler.isEmpty())
        {
            checkOK = false;
            String meldung = "";
            lbl_fehlerHinzu.setVisible(true);
            lbl_fehlerHinzu.setText(link);
            Iterator<String> iter = fehler.iterator();            
            while(iter.hasNext())
            {                
                meldung = meldung + iter.next();
                lbl_fehlerHinzu.setText(meldung);
                lbl_fehlerHinzu.setStyle("-fx-text-fill: red;");    
            }            
        }
        return  checkOK;        
    }

    /***
     * Methode zum Speichern eines Assets in der Datenbank
     * Im Hinblick auf der zukünftigen weiteren Umsetzung müssten die Assets vom
     * Quellort zu einem entsprechenden Zielordner (Je nach Typ und Kategorie) kopiert werden
     * @return : boolean | ist das Speichern erfolgreich?
     */
    private boolean saveAssetInDB()
    {
        boolean save = false;
        if( checkData() )
        {
            // Aufbau der Datenbankverbindung
            DBConnect conKatId = new DBConnect();
            int katId = conKatId.getAssetCategoryID(String.valueOf(dd_kat.getValue()));

            DBConnect conTypId = new DBConnect();
            int typId = conTypId.getAssetTypeID(String.valueOf(dd_typ.getValue()));

            DBConnect conSaveAsset = new DBConnect();
            
            // Die Speichermethode funktioniert nicht!!!
            System.out.println("Assetname:: " + assetName);
            System.out.println("assetPath:: " + assetPath);
            System.out.println("dd_kat" + String.valueOf(dd_kat.getValue()));
            System.out.println("dd_typ" + String.valueOf(dd_typ.getValue()));
            System.out.println("Typ:: " + typId);
            System.out.println("Kat:: " + katId);
            System.out.println("ID:: " + TempData.getBenutzer().getId());
            
          // eigentliche Speicherung in der Datebank (einige Parameter sind noch Dummys "1,1,1")
          if(conSaveAsset.addAsset(assetName,assetPath,1,1,1))
           {
                save = true;
           } 
        }
        System.out.print("save war :: " + save);
        return save;
    }
    
    /***
     * 
     * @param url : Amazon Url die geprüft werden soll
     * @return : boolean --> ist der Amazonlink regexkonform?
     * quelle: www.neowin.net/forum/topic/853774-java-regex-to-validate-url/
     */
    private boolean checkRegex(String url)
    {
        Matcher link  = Pattern.compile(
	new StringBuilder()
		.append("((?:(http|https|Http|Https|rtsp|Rtsp):")
		.append("\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)")
			.append("\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_")
			.append("\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?")
			.append("((?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}\\.)+")   // named host
			.append("(?:")   // plus top level domain
			.append("(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])")
			.append("|(?:biz|b[abdefghijmnorstvwyz])")
			.append("|(?:cat|com|coop|c[acdfghiklmnoruvxyz])")
			.append("|d[ejkmoz]")
			.append("|(?:edu|e[cegrstu])")
			.append("|f[ijkmor]")
			.append("|(?:gov|g[abdefghilmnpqrstuwy])")
			.append("|h[kmnrtu]")
			.append("|(?:info|int|i[delmnoqrst])")
			.append("|(?:jobs|j[emop])")
			.append("|k[eghimnrwyz]")
			.append("|l[abcikrstuvy]")
			.append("|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])")
			.append("|(?:name|net|n[acefgilopruz])")
			.append("|(?:org|om)")
			.append("|(?:pro|p[aefghklmnrstwy])")
			.append("|qa")
			.append("|r[eouw]")
			.append("|s[abcdeghijklmnortuvyz]")
			.append("|(?:tel|travel|t[cdfghjklmnoprtvwz])")
			.append("|u[agkmsyz]")
			.append("|v[aceginu]")
			.append("|w[fs]")
			.append("|y[etu]")
			.append("|z[amw]))")
			.append("|(?:(?:25[0-5]|2[0-4]") // or ip address
			.append("[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(?:25[0-5]|2[0-4][0-9]")
			.append("|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1]")
			.append("[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}")
			.append("|[1-9][0-9]|[0-9])))")
			.append("(?:\\:\\d{1,5})?)") // plus option port number
			.append("(\\/(?:(?:[a-zA-Z0-9\\;\\/\\?\\:\\@\\&\\=\\#\\~")  // plus option query params
			.append("\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?")
			.append("(?:\\b|$)").toString()
		).matcher(url);        
    return link.matches();
    }
    
    /***
     * Erlaubt es eine neue Assetkategorie hinzuzufügen wenn die Kategorie 
     * wenn die Kategorie nicht bereits in der Datenbank hinterlegt ist.
     * @param event 
     */
    @FXML
    private void addKat(ActionEvent event)
    {   
        String meldung = "";
        String kat = inp_addKat.getText();
        DBConnect con = new DBConnect();
        if(!kat.equals(""))
        {       
            // Holt bereits vorhandene Kategorien zum späteren Abgleichen
            ArrayList<String[]> kategorien = con.getCategorys();
            
            Iterator<String[]> iter = kategorien.iterator();            
            while(iter.hasNext())
            {                   
                String[] katArray = iter.next();
                System.out.println(katArray[1]);
                System.out.println(katArray[2]);
                if(kat.equals(katArray[1])) 
                {
                    meldung = "Asset-Kategorie bereits vorhanden!";
                    lbl_addKat.setText(meldung);
                } 
            } 
            // Wenn keine Fehlermeldungen vorhanden sind  
            if(meldung.equals(""))
            {
                if(con.addAssetCategory(kat))
                {                
                    lbl_addKat.setText("Kategorie hinzugefügt!");
                    inp_addKat.setText("");                
                }
            } 
        // Alternativzweig wenn keine Eingabe gemacht wurde
        }else{
           meldung = "Keine Eingabe getätigt!";
           lbl_addKat.setText(meldung);    
        }        
    }
    
    /***
     * Methode um Unterkategorien hinzuzufügen
     * @param event 
     */
    @FXML
    private void addUnterKat(ActionEvent event)
    {
        // lokale Variablen leer initialisieren
        String subKat = "";
        String meldung = "";
        
        // Eingabewerte holen
        String hauptKat = String.valueOf(dd_katOverview.getValue());
        subKat = inp_unterKat.getText();
        
        // DB Verbindung aufbauen
        DBConnect conSubKats = new DBConnect();
        /***
         * Alle Subkategorien zum Vergleichen holen (Doppelte Erfassung damit nicht möglich)
         * Anmerkung Nacharbeit: Es müsste künftig nicht nur geprüft werden ob die Unterkategorie
         * einmalig ist, sondern ob diese einmal in der Hauptkategorie ist
         ***/
        ArrayList<String> allSubkats = conSubKats.getSubCategorys();
        
        Iterator<String> iter = allSubkats.iterator();            
            while(iter.hasNext())
            {                   
                String vorhandeneSubKat = iter.next();                
                if(subKat.equals(vorhandeneSubKat))
                {
                    meldung = "Unterkategorie bereits vorhanden!";
                    lbl_unterKat.setText(meldung);
                }
            } 
        if(hauptKat.equals("null")|| subKat.equals(""))
        {
            System.out.println("Keine Hauptkat oder :: " + hauptKat);
            meldung = "Eingaben fehlen!";
            lbl_unterKat.setText(meldung);
        }
                
        // Wenn keine Meldung vorhanden wird der DB Eintrag vorgenommen
        if(meldung.equals(""))
        {        
            DBConnect con = new DBConnect();
            if(con.addSubCategory(subKat,hauptKat))lbl_unterKat.setText("Unterkategorie hinzugefügt!");
        }
    }
    
    /***
     * Methode um Assettypen der DB hinzuzufügen
     * Hier müssten später noch Ordner erzeugt werden, die auf dem lokalen Rechner
     * die Typen repräsentieren
     * @param event 
     */
    @FXML
    private void addTyp(ActionEvent event)
    { 
        String meldung = "";
        String inputTyp = inp_addTyp.getText();
        if(!inputTyp.equals(""))
        {
            DBConnect con = new DBConnect();
            // Auslesen aller bereits vorhanden Typen
            ArrayList<String[]> typen = con.getAssetTypes();
            
            Iterator<String[]> iter = typen.iterator();  
            // Vergleicht Eingabe mit bereits vorhandenen Typen
            while(iter.hasNext())
            {                   
                String[] typ = iter.next();
                if(inputTyp.equals(typ[1]))
                {
                    meldung = "Asset-Typ bereits vorhanden!";
                    lbl_addTyp.setText(meldung);
                }
            } 
            
            // Speicherung wenn keine Meldung vorhanden ist
            if(meldung.equals(""))
            {
                if(con.addAssetType(inputTyp))
                {
                    lbl_addTyp.setText("Typ erfolgreich hinzugefügt!");
                    inp_addTyp.setText("");
                }
            }
            // Wenn keine Eingabe vorhanden ist
        }else{
           lbl_addTyp.setText("Eingabe fehlt!");
        }     
    } 
} // END  - AssetController


